﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows.Data;
using DemoApp.Properties;
using Microsoft.Practices.Unity;

namespace DemoApp.ViewModel
{
    /// <summary>
    ///     The ViewModel for the application's main window.
    /// </summary>
    public class MainWindowViewModel : WorkspaceViewModel, IMainWindowViewModel
    {
        #region Fields

        private ObservableCollection<WorkspaceViewModel> _workspaces;
        private readonly IUnityContainer _container;

        #endregion // Fields

        #region Constructor

        public MainWindowViewModel(IUnityContainer container)
        {
            base.DisplayName = Strings.MainWindowViewModel_DisplayName;
            _container = container;

            Commands = new ObservableCollection<CommandViewModel>();
        }

        #endregion // Constructor

        #region Commands

        /// <summary>
        ///     Returns a read-only list of commands
        ///     that the UI can display and execute.
        /// </summary>
        public ObservableCollection<CommandViewModel> Commands { get; private set; }

        public void AddCommand<T>(T command)
            where T:CommandViewModel
        {
            Commands.Add(command);
        }

        #endregion // Commands

        #region Workspaces

        /// <summary>
        ///     Returns the collection of available workspaces to display.
        ///     A 'workspace' is a ViewModel that can request to be closed.
        /// </summary>
        public ObservableCollection<WorkspaceViewModel> Workspaces
        {
            get
            {
                if (_workspaces == null)
                {
                    _workspaces = new ObservableCollection<WorkspaceViewModel>();
                    _workspaces.CollectionChanged += OnWorkspacesChanged;
                }
                return _workspaces;
            }
        }

        public void AddWorkspace<T>()
            where T : WorkspaceViewModel
        {
            var workspace = Workspaces.FirstOrDefault(vm => vm is T) as T;

            if (workspace == null)
            {
                workspace = _container.Resolve<T>();
                AddWorkspace(workspace);
            }
            SetActiveWorkspace(workspace);
        }

        public void AddWorkspace<T>(T workspace)
            where T : WorkspaceViewModel
        {
            Workspaces.Add(workspace);
            SetActiveWorkspace(workspace);
        }
        
        private void SetActiveWorkspace(WorkspaceViewModel workspace)
        {
            Debug.Assert(_workspaces.Contains(workspace));

            ICollectionView collectionView = CollectionViewSource.GetDefaultView(_workspaces);
            if (collectionView != null)
                collectionView.MoveCurrentTo(workspace);
        }

        private void OnWorkspacesChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.NewItems)
                    workspace.RequestClose += OnWorkspaceRequestClose;

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.OldItems)
                    workspace.RequestClose -= OnWorkspaceRequestClose;
        }

        private void OnWorkspaceRequestClose(object sender, EventArgs e)
        {
            var workspace = sender as WorkspaceViewModel;
            workspace.Dispose();
            Workspaces.Remove(workspace);
        }

        #endregion // Workspaces
    }
}